package com.example.bookservice.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.bookservice.dto.AuthorBookDto;
import com.example.bookservice.dto.BooksDTO;
import com.example.bookservice.dto.RequestParamsDto;
import com.example.bookservice.entity.Book;
import com.example.bookservice.entity.Chapter;
import com.example.bookservice.service.BookService;
import com.example.bookservice.service.ChapterService;
import com.example.bookservice.vo.PageResultVo;
import com.example.commom.enums.RespDescEnum;
import com.example.commom.enums.RoleType;
import com.example.commom.enums.StatusCodeEnum;
import com.example.commom.utils.AdminVerifyUtils;
import com.example.commom.utils.JwtUtils;
import com.example.feign.result.AjaxResult;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 软工2104-李家强-2100770248
 * @since 2023-09-20
 */
@Slf4j
@Transactional
@RestController
@RequestMapping("/book")
public class BookController {

    @Autowired
    private AdminVerifyUtils adminVerifyUtils;

    @Autowired
    private BookService bookService;

    @Autowired
    private ChapterService chapterService;

    @GetMapping("/{bookId}")
    @ApiOperation(value = "测试接口1", notes = "通过id查询单本书")
    public AjaxResult getBookById(@PathVariable("bookId") Long bookId) {

        return AjaxResult.success(StatusCodeEnum.OK.getCode(), bookService.getById(bookId));
    }

    /**
     *  读者浏览全部图书
     */
    @PostMapping("/getAllBooks")
    @ApiOperation(value = "读者浏览全部图书", notes = "读者浏览全部图书")
    public AjaxResult getAllBooks(@RequestBody BooksDTO booksDTO) {

        return bookService.getAllBooks(booksDTO);
    }

    /**
     *  读者按照作者名或者书名搜索书籍
     */
    @PostMapping("/searchByAuthorOrBook")
    @ApiOperation(value = "读者按照作者名或者书名搜索书籍", notes = "读者按照作者名或者书名搜索书籍")
    public AjaxResult searchByAuthorOrBook(@RequestBody RequestParamsDto params) {


        PageResultVo<?> books = bookService.searchByAuthorOrBook(params);

        return AjaxResult.success(StatusCodeEnum.OK.getCode(), books);
    }

    /**
     *  作者浏览全部审核通过/未通过的图书
     */
    @PostMapping("/getAuthorBooks")
    @ApiOperation(value = "作者浏览全部 可用/不可用 的图书", notes = "参数是用户名,和approved path 参数")
    public AjaxResult getAuthorIsAvailableBooks(@RequestHeader("token") String token,
                                                @RequestBody AuthorBookDto authorBookDto) {

        if (authorBookDto.getAvailable() == null) {
            return AjaxResult.fail(RespDescEnum.MissRequiredParameter.getValue());
        }

        String tokenUsername = JwtUtils.getUserNameByToken(token);

        if (tokenUsername == null) {
            return AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }

        authorBookDto.setAuthor(tokenUsername);

        PageResultVo<?> resultVo = bookService.getAuthorIsAvailableBooks(authorBookDto);
        return AjaxResult.success(StatusCodeEnum.OK.getCode(), resultVo);
    }


    /**
     *  新增书籍
     */
    @PostMapping("/insertBook")
    @ApiOperation(value = "新增书籍", notes = "参数是书籍对象")
    public AjaxResult insertBook(@Validated @RequestBody Book book,
                                 @RequestHeader(value = "token") String token) {

        book.setBookId(null);

        // 拿到用户已经登陆的用户名
        String username = JwtUtils.getUserNameByToken(token);
        // 拿到用户的类型
        String userType = JwtUtils.getUserTypeByToken(token);

        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(userType)) {
            return AjaxResult.fail(StatusCodeEnum.Redirect.getCode(), StatusCodeEnum.Redirect.getMsg());
        }

        if (!RoleType.WRITER.getValue().equals(userType)) {
            // 该用户不是作者.
            return AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }

        return bookService.insertOrUpdateBook(book, username);
    }


    /**
     * 根据id 删除书籍
     */
    @PostMapping("/deleteBook")
    @ApiOperation(value = "根据id 删除书籍", notes = "参数是书籍id")
    public AjaxResult deleteBook(@RequestParam("id")  Long id, @RequestHeader(value = "token") String token) {
        // 拿到用户已经登陆的用户名
        String username = JwtUtils.getUserNameByToken(token);
        // 拿到用户的类型
        String userType = JwtUtils.getUserTypeByToken(token);

        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(userType)) {
            return AjaxResult.fail(StatusCodeEnum.Redirect.getCode(), StatusCodeEnum.Redirect.getMsg());
        }

        if (!RoleType.WRITER.getValue().equals(userType)) {
            return  AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }
        return bookService.deleteBookById(id);
    }

    /**
     *  修改书籍, 利用kafka来操作
     *  bin/kafka-topics.sh --bootstrap-server 192.168.6.129:9092 --topic book-topic --create --partitions 1 --replication-factor 2
     */
    @PostMapping("/updateBook")
    @ApiOperation(value = "作者修改书籍信息", notes = "参数是书籍对象, 一定要包含id")
    public AjaxResult updateBook(@RequestBody Book book,
                                 @RequestHeader(value = "token") String token) {

        if (book.getBookId() == null) {
            return AjaxResult.fail(StatusCodeEnum.FAILED.getCode(), RespDescEnum.MissRequiredParameter.getValue());
        }

        book.setIsAvailable(null);
        book.setAuthor(null);
        book.setAverageMark(null);
        book.setPublicationDate(null);
        book.setReadeCount(null);

        // 修改后, 需要重新审核.
        book.setIsApproved(false);

        // 判断 id 是否有效
        Book bookInfo = bookService.getById(book.getBookId());
        if (bookInfo == null) {
            return AjaxResult.fail(StatusCodeEnum.FAILED.getCode(), RespDescEnum.MissRequiredParameter.getValue());
        }

        // 拿到用户已经登陆的用户名
        String username = JwtUtils.getUserNameByToken(token);

        // 拿到用户的类型
        String userType = JwtUtils.getUserTypeByToken(token);

        if (!StringUtils.hasLength(userType) || !StringUtils.hasLength(username)) {
            return AjaxResult.fail(StatusCodeEnum.Redirect.getCode(), StatusCodeEnum.Redirect.getMsg());
        }

        if (!bookInfo.getAuthor().equals(username)) {
            // 不是作者本人, 不能修改!
            return AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }

        if (RoleType.READER.getValue().equals(userType)) {
            // 该用户不是作者.
            return AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }

        return bookService.insertOrUpdateBook(book, null);
    }


    /**
     *  新增 书籍章节
     */
    @PostMapping("/insertChapter")
    @ApiOperation(value = "新增书籍章节", notes = "参数是书籍id,和章节对象")
    public AjaxResult insertChapter(@Validated @RequestBody Chapter chapter,
                                    @RequestHeader(value = "token") String token) {
        chapter.setChapterId(null);

        // 通过 bookId 查询书籍信息
        Book book = bookService.getById(chapter.getBookId());
        if (book == null) {
            return AjaxResult.fail(StatusCodeEnum.FAILED.getCode(), RespDescEnum.MissRequiredParameter.getValue());
        }

        // 判断书籍作者和登录用户是否匹配
        if (!book.getAuthor().equals(JwtUtils.getUserNameByToken(token))) {
            return AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }

        // 执行 插入/新增 操作
        return bookService.insertOrUpdateChapter(chapter.getBookId(), chapter);
    }

    /**
     *  删除书籍章节
     */
    @PostMapping("/deleteChapter")
    @ApiOperation(value = "根据id 删除章节", notes = "参数是章节id")
    public AjaxResult deleteChapter(@RequestParam("id")  Long id, @RequestHeader(value = "token") String token) {
        // 拿到用户已经登陆的用户名
        String username = JwtUtils.getUserNameByToken(token);
        // 拿到用户的类型
        String userType = JwtUtils.getUserTypeByToken(token);

        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(userType)) {
            return AjaxResult.fail(StatusCodeEnum.Redirect.getCode(), StatusCodeEnum.Redirect.getMsg());
        }

        if (RoleType.READER.getValue().equals(userType)) {
            return  AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }
        return bookService.deleteChapterById(id);
    }


    /**
     *  修改 书籍章节
     */
    @PostMapping("/updateChapter")
    @ApiOperation(value = "修改书籍章节", notes = "参数是书籍id,和章节对象")
    public AjaxResult updateChapter(@RequestBody Chapter chapter,
                                    @RequestHeader(value = "token") String token) {

        // 修改, id 不能为空.
        if (chapter.getChapterId() == null) {
            return AjaxResult.fail(StatusCodeEnum.FAILED.getCode(), RespDescEnum.MissRequiredParameter.getValue());
        }

        // 查询 章节 id 是否有效
        Chapter chapterServiceById = chapterService.getById(chapter.getChapterId());
        if (chapterServiceById == null) {
            return AjaxResult.fail(StatusCodeEnum.FAILED.getCode(), RespDescEnum.MissRequiredParameter.getValue());
        }

        // 通过 bookId 查询书籍信息
        Book book = bookService.getById(chapterServiceById.getBookId());
        if (book == null) {
            return AjaxResult.fail(StatusCodeEnum.FAILED.getCode(), RespDescEnum.AccountNotExistence.getValue());
        }

        // 判断书籍作者和登录用户是否匹配
        if (!book.getAuthor().equals(JwtUtils.getUserNameByToken(token))) {
            return AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }

        // 执行 修改 操作
        return bookService.insertOrUpdateChapter(null, chapter);
    }


    /**
     *  查看指定书籍的详情(获取书籍全部章节)
     */
    @GetMapping("/getBookInfo/{targetBook}")
    @ApiOperation(value = "查看指定书籍的详情", notes = "参数是书籍id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "targetBook", value = "书籍 id",
                    dataType = "long", paramType = "path", required = true)
    })
    public AjaxResult getBookInfo(@PathVariable("targetBook") Long targetBook) {

        // 参数校验
        if (targetBook == null) {
            return AjaxResult.fail(RespDescEnum.MissRequiredParameter.getValue());
        }

        return AjaxResult.success(bookService.getBookInfo(targetBook));
    }


    /**
     *  查看指定书籍指定章节的详情信息
     */
    @GetMapping("/getChapterInfo/{targetBook}/{targetChapter}")
    @ApiOperation(value = "查看指定书籍指定章节的详情信息", notes = "参数是书籍id,和章节id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "targetBook", value = "书籍 id"
                    , dataType = "long", paramType = "path", required = true)
    })
    public AjaxResult getChapterInfo(@PathVariable("targetBook") Long targetBook,
                                     @PathVariable("targetChapter") Long targetChapter ) {

        // 参数校验
        if (targetBook == null || targetChapter == null) {
            return AjaxResult.fail(RespDescEnum.MissRequiredParameter.getValue());
        }

        Chapter chapter = bookService.getChapterInfo(targetBook, targetChapter);

        return AjaxResult.success(chapter);
    }



    /**
     *  通过书籍id,章节id查看具体章节是否存在
     */
    @GetMapping("/bookIsExist/{targetBook}/{targetChapter}")
    @ApiOperation(value = "通过书籍id,章节id查看具体章节是否存在", notes = "参数是书籍id, 章节id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "targetBook", value = "书籍 id"
                    , dataType = "long", paramType = "path", required = true),
            @ApiImplicitParam(name = "targetChapter", value = "章节 id"
                    , dataType = "long", paramType = "path", required = true)
    })
    public Boolean bookIsExist(@PathVariable("targetBook") Long targetBook,
                               @PathVariable("targetChapter") Long targetChapter) {

        // 参数校验
        if (targetBook == null || targetChapter == null) {
            return false;
        }

        LambdaQueryWrapper<Chapter> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Chapter::getBookId, targetBook)
                .eq(Chapter::getChapterId, targetChapter);

        Chapter chapter = chapterService.getOne(lambdaQueryWrapper);

        return chapter != null;
    }


    /**
     *  通过书籍id查询作者
     */
    @GetMapping("/getAuthorByBookId/{targetBook}")
    @ApiOperation(value = "通过书籍id查询作者", notes = "参数是书籍id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "targetBook", value = "书籍 id"
                    , dataType = "long", paramType = "path", required = true)
    })
    public String getAuthorByBookId(@PathVariable("targetBook") Long targetBook) {

        // 参数校验
        if (targetBook == null ) {
            return null;
        }

        LambdaQueryWrapper<Book> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Book::getBookId, targetBook);

        Book book = bookService.getOne(lambdaQueryWrapper);

        return book.getAuthor();
    }



    /**
     *  管理员获取全部的未审核的图书[新发布的书籍/修改过书籍信息的书籍]
     */
    @GetMapping("/admin/approved/book/false")
    @ApiOperation(value = "管理员获取全部的未审核的图书", notes = "管理员获取全部的未审核的图书")
    public AjaxResult getApprovedFalse(@RequestHeader("token") String token,
                                       @RequestParam("pageNum") Integer pageNum,
                                       @RequestParam("pageSize") Integer pageSize) {

        boolean flag = adminVerifyUtils.verity(token);
        if (!flag) {
            return AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }

        if (pageNum <= 0) {
            pageNum = 1;
        }
        if (pageSize <= 0) {
            pageSize = 20;
        }

        return bookService.getApprovedBookFalse(pageNum, pageSize);
    }

    /**
     *  管理员获取全部的未审核的章节[新发布的章节/修改过书籍信息的章节]
     */
    @GetMapping("/admin/approved/chapter/false")
    @ApiOperation(value = "管理员获取全部的未审核的章节", notes = "管理员获取全部的未审核的章节")
    public AjaxResult getApprovedChapterFalse(@RequestHeader("token") String token,
                                       @RequestParam("pageNum") Integer pageNum,
                                       @RequestParam("pageSize") Integer pageSize) {

        boolean flag = adminVerifyUtils.verity(token);
        if (!flag) {
            return AjaxResult.fail(StatusCodeEnum.UNAUTHORIZED.getCode(), StatusCodeEnum.UNAUTHORIZED.getMsg());
        }

        if (pageNum <= 0) {
            pageNum = 1;
        }
        if (pageSize <= 0) {
            pageSize = 20;
        }

        return bookService.getApprovedChapterFalse(pageNum, pageSize);
    }


    /**
     *  管理员审核书籍id是否正确
     */
    @GetMapping("/admin/approved/book/{bookId}")
    @ApiOperation(value = "管理员审核书籍id是否正确", notes = "参数是书籍id")
    public boolean isCorrectBookId(@PathVariable("bookId") Long bookId,
                                  @RequestHeader("token") String token) {
        // 1. 权限校验
        boolean flag = adminVerifyUtils.verity(token);
        if (!flag) {
            return false;
        }

        return bookService.getById(bookId) != null;
    }

    /**
     *  管理员审核章节id是否正确
     */
    @GetMapping("/admin/approved/chapter/{chapterId}")
    @ApiOperation(value = "管理员审核章节id是否正确", notes = "参数是章节id")
    public boolean isCorrectChapterId(@PathVariable("chapterId") Long chapterId,
                                  @RequestHeader("token") String token) {
        // 1. 权限校验
        boolean flag = adminVerifyUtils.verity(token);
        if (!flag) {
            return false;
        }

        return chapterService.getById(chapterId) != null;
    }

    /**
     *  搜索书籍自动补全搜索框
     */
    @GetMapping("/suggestions")
    @ApiOperation(value = "搜索书籍自动补全搜索框", notes = "搜索书籍自动补全搜索框")
    public AjaxResult suggestions(@RequestParam("key") String prefix) {
        return bookService.suggestions(prefix);
    }

    /**
     *  搜索章节自动补全搜索框
     */
    @GetMapping("/suggestions/{targetBookId}")
    @ApiOperation(value = "搜索章节自动补全搜索框", notes = "搜索章节自动补全搜索框")
    public AjaxResult suggestionChapter(@PathVariable("targetBookId") Long bookId,
                            @RequestParam("key") String prefix) {
        return bookService.suggestionChapter(bookId, prefix);
    }

}
